package top.xtcoder.jdcbase.base.utils;

import java.lang.reflect.Field;
import java.util.ArrayList;
import java.util.Arrays;
import java.util.HashMap;
import java.util.List;
import java.util.Map;

import org.nutz.json.Json;
import org.nutz.lang.Strings;

import top.xtcoder.jdcbase.base.common.Funs;

public class ChildNodeUtil {
	/**
	 * list数组转化为tree数据, <br>
	 * <p color="red">T类型里必须包含idName, pidName字段，childrenName类型必须是T</p>
	 * @param <T> 数据类型，必须包含idName, pidName字段和List<T> childrenName字段
	 * @param list 数据list
	 * @param idName 数据id字段名，比如id等等
	 * @param pidName 父id字段名，比如pid、parentId等等
	 * @param pidFirstValue 第一层的pid值，比如0等等
	 * @param childrenName children的字段名，比如children、childrens等等
	 * @return
	 */
	public static <T> List<T> list2tree(List<T> list, String idName, String pidName, String pidFirstValue, String childrenName) {
		if(list == null || list.size() <= 0) {
			return list;
		}
		try {
			Map<String, List<T>> maps = list2pidMap(list, idName, pidName);
			List<T> treeList = maps.get(pidFirstValue);
			handleTree(treeList, maps, idName, childrenName);
			return treeList;
		}catch(Exception e) {
			e.printStackTrace();
			throw new RuntimeException(e);
		}
	}
	
	private static <T> void handleTree(List<T> list, 
			Map<String, List<T>> maps,
			String idName,
			String childrenName) throws Exception{
		if(list != null && list.size() > 0) {
			for(T item : list){
				Map<String, Field> fields = getAllField(item, true);
				Field idField = fields.get(idName);
				idField.setAccessible(true);
				String idValue = (String) idField.get(item);
				
				List<T> children = maps.get(idValue);
				if(children != null) {
					handleTree(children, maps, idName, childrenName);
					Field childrenField = fields.get(childrenName);
					childrenField.setAccessible(true);
					childrenField.set(item, children);
				}
			}
		}
	}
	
	/**
	 * 数据转换 为map形式 {
	 * 	pid1: List<T> list1,<br>
	 *  pid2: List<T> list2,...
	 * }
	 * @param <T>
	 * @param list
	 * @param idName
	 * @param pidName
	 * @return
	 * @throws Exception
	 */
	private static <T> Map<String, List<T>> list2pidMap(List<T> list, String idName, String pidName) throws Exception {
		Map<String, List<T>> maps = new HashMap();
		for(int i = 0; i < list.size(); i ++) {
			Map<String, Field> fields = getAllField(list.get(i), true);
			Field field = fields.get(idName);
			if(field == null) {
				throw new Exception("list数据的第【" + i + "】条数据没有【" + idName + "】字段");
			}
			Field pidField = fields.get(pidName);
			if(pidField == null) {
				throw new Exception("list数据的第【" + i + "】条数据没有【" + pidName + "】字段");
			}
			pidField.setAccessible(true);
			String pidKey = (String) pidField.get(list.get(i));
			List<T> subList = maps.get(pidKey);
			if(subList == null) {
				subList = new ArrayList<T>();
			}
			subList.add(list.get(i));
			maps.put(pidKey, subList);
		}
		return maps;
	}
	
	/**
	 * 获取data的所有字段
	 * @param <T>
	 * @param data 数据
	 * @param extend 是否获取继承类的
	 * @return
	 */
	public static <T> Map<String, Field> getAllField(T data, boolean extend) {
		Class<T> cls = (Class<T>) data.getClass();
		List<Field> fs = new ArrayList<>();
		do {
			Field[] pfs = cls.getDeclaredFields();
			fs.addAll(Arrays.asList(pfs));
			cls = (Class<T>) cls.getSuperclass();
		}while(extend && !Strings.equals(cls.getName(), Object.class.getName()));
		Map<String, Field> map = new HashMap();
		if(fs == null) {
			return map;
		}
		fs.forEach((f) -> {
			map.put(f.getName(), f);
		});
		return map;
	}
}
